home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / lib / libpq / be-dumpdata.c next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  8.3 KB  |  322 lines

  1. /* ----------------------------------------------------------------
  2.  *   FILE
  3.  *    be-dumpdata.c
  4.  *    
  5.  *   DESCRIPTION
  6.  *    support for collection of returned tuples from an internal
  7.  *    PQ call into a backend buffer.
  8.  *
  9.  *   INTERFACE ROUTINES
  10.  *    be_portalinit    - initialize backend portal administration
  11.  *    be_portalpush    - add a portal to the top of the portal stack
  12.  *    be_portalpop     - remove portal on the top of the stack & return it
  13.  *    be_currentportal - return the top portal on the portal stack
  14.  *    be_newportal     - return a new portal.
  15.  *    be_portalinit    - initialize backend portal expected to hold results.
  16.  *    be_printtup      - add a tuple to a backend portal
  17.  *
  18.  *   NOTES
  19.  *    Since backend user-defined operators can call queries
  20.  *    which in turn call user-defined operators can call queries...
  21.  *    we have to keep track of portals on a stack.  BeginCommand()
  22.  *    puts portals on the stack and the PQ functions remove them.
  23.  *
  24.  *   IDENTIFICATION
  25.  *    $Header: /private/postgres/src/lib/libpq/RCS/be-dumpdata.c,v 1.4 1992/02/25 16:45:44 clarsen Exp $
  26.  * ----------------------------------------------------------------
  27.  */
  28.  
  29. #include "tmp/postgres.h"
  30.  
  31. RcsId("$Header: /private/postgres/src/lib/libpq/RCS/be-dumpdata.c,v 1.4 1992/02/25 16:45:44 clarsen Exp $");
  32.  
  33. #include "tmp/simplelists.h"
  34. #include "tmp/libpq-be.h"
  35.  
  36. #include "access/heapam.h"
  37. #include "access/htup.h"
  38. #include "storage/buf.h"
  39. #include "utils/memutils.h"
  40. #include "utils/fmgr.h"
  41. #include "utils/mcxt.h"
  42. #include "utils/log.h"
  43. #include "utils/exc.h"
  44.  
  45. #include "catalog/syscache.h"
  46. #include "catalog/pg_type.h"
  47.  
  48. extern ObjectId typtoout();
  49.  
  50. /* ----------------
  51.  *    backend portal stack for recursive PQexec calls
  52.  * ----------------
  53.  */
  54. typedef struct PortalStackElement {
  55.     PortalEntry   *entry;
  56.     SLNode       Node;
  57. } PortalStackElement;
  58.  
  59. SLList be_portalstack;
  60.  
  61. /* ----------------
  62.  *    be_portalinit - initialize backend portal administration
  63.  *
  64.  *    This is called once from InitPostgres() to initialize
  65.  *    the portal stack.
  66.  * ----------------
  67.  */
  68. void
  69. be_portalinit()
  70. {
  71.     SLNewList(&be_portalstack, offsetof(PortalStackElement, Node));
  72. }
  73.  
  74. /* ----------------
  75.  *    be_portalpush - add a portal to the top of the portal stack
  76.  *
  77.  *    used by BeginCommand()
  78.  * ----------------
  79.  */
  80. void
  81. be_portalpush(entry)
  82.     PortalEntry *entry;
  83. {
  84.     PortalStackElement *elemptr;
  85.  
  86.     elemptr = (PortalStackElement *) palloc(sizeof(PortalStackElement));
  87.     elemptr->entry = entry;
  88.     SLNewNode(&(elemptr->Node));
  89.     SLAddTail(&be_portalstack, &(elemptr->Node));
  90. }
  91.  
  92. /* ----------------
  93.  *    be_portalpop - remove the portal on the top of the stack & return it
  94.  *
  95.  *    used by PQexec()
  96.  * ----------------
  97.  */
  98. PortalEntry *
  99. be_portalpop()
  100. {
  101.     PortalStackElement *elemptr;
  102.     PortalEntry *entry;
  103.     
  104.     elemptr = (PortalStackElement *) SLRemTail(&be_portalstack);
  105.     if (elemptr == NULL)
  106.     return NULL;
  107.     
  108.     entry = elemptr->entry;
  109.     pfree(elemptr);
  110.     return entry;
  111. }
  112.  
  113. /* ----------------
  114.  *    be_currentportal - return the top portal on the portal stack
  115.  *
  116.  *    used by be_printtup()
  117.  * ----------------
  118.  */
  119. PortalEntry *
  120. be_currentportal()
  121. {
  122.     PortalStackElement *elemptr;
  123.     
  124.     elemptr = (PortalStackElement *) SLGetTail(&be_portalstack);
  125.     if (elemptr == NULL)
  126.     return NULL;
  127.     
  128.     return elemptr->entry;
  129. }
  130.  
  131. /* ----------------
  132.  *    be_newportal - return a new portal.
  133.  *
  134.  *    If the user-defined function does not specify a portal name,
  135.  *    we generate a unique one.  Names are generated from a combination
  136.  *    of a postgres oid and an integer counter which is incremented
  137.  *    every time we ask for a local portal.
  138.  *
  139.  *    used by BeginCommand()
  140.  * ----------------
  141.  */
  142.  
  143. ObjectId be_portaloid;
  144. u_int     be_portalcnt = 0;
  145.  
  146. PortalEntry *
  147. be_newportal()   
  148. {
  149.     PortalEntry *entry;
  150.     char     buf[PortalNameLength];
  151.     
  152.     /* ----------------
  153.      *    generate a new name
  154.      * ----------------
  155.      */
  156.     if (be_portalcnt == 0)
  157.     be_portaloid = newoid();
  158.     be_portalcnt++;
  159.     sprintf(buf, "be_%d_%d", be_portaloid, be_portalcnt);
  160.     
  161.     /* ----------------
  162.      *    initialize the new portal entry and keep track
  163.      *  of the current memory context for be_printtup().
  164.      *  This is important - otherwise whatever we allocate
  165.      *  will go away and the contents of the portal after
  166.      *  PQexec() returns will be meaningless.
  167.      * ----------------
  168.      */
  169.     entry = pbuf_setup(buf);
  170.     entry->portalcxt = (Pointer) CurrentMemoryContext;
  171.     
  172.     return entry;
  173. }
  174.  
  175. /* ----------------
  176.  *    be_typeinit - initialize backend portal expected to hold
  177.  *            query results.
  178.  *
  179.  *    used by BeginCommand()
  180.  * ----------------
  181.  */
  182. void
  183. be_typeinit(entry, attrs, natts)
  184.     PortalEntry     *entry;
  185.     struct attribute     **attrs;
  186.     int         natts;
  187. {
  188.     PortalBuffer     *portal;
  189.     GroupBuffer     *group;
  190.     TypeBlock         *types, *type;
  191.     int         i;
  192.  
  193.     /* ----------------
  194.      *    add a new portal group to the portal
  195.      * ----------------
  196.      */
  197.     portal = entry->portal;
  198.     portal->no_groups++;
  199.     portal->groups = group = pbuf_addGroup(portal);
  200.     group->no_fields = natts;
  201.  
  202.     /* ----------------
  203.      *    initialize portal group type info
  204.      * ----------------
  205.      */
  206.     if (natts > 0) {
  207.     type = types = group->types = pbuf_addTypes(natts);
  208.     for (i = 0; i < natts; ++i) {
  209.         strncpy(types->name, attrs[i]->attname, NameLength);
  210.         type->adtid = attrs[i]->atttypid;
  211.         type->adtsize = attrs[i]->attlen;
  212.         type++;
  213.     }
  214.     }
  215. }
  216.         
  217. /* ----------------
  218.  *    be_printtup - add a tuple to a backend portal
  219.  *
  220.  *    used indirectly by ExecRetrieve()
  221.  *
  222.  *    This code is pretty much copied from printtup(), dump_type()
  223.  *    and dump_data().  -cim 2/12/91
  224.  * ----------------
  225.  */
  226. void
  227. be_printtup(tuple, typeinfo) 
  228.     HeapTuple        tuple;
  229.     struct attribute     *typeinfo[];
  230. {
  231.     int        i;
  232.     char    *attr;
  233.     Boolean    isnull;
  234.     ObjectId    typoutput;
  235.     
  236.     PortalEntry  *entry = NULL;
  237.     PortalBuffer *portal = NULL;
  238.     GroupBuffer  *group = NULL ;
  239.     TupleBlock      *tuples = NULL;
  240.     char      **values;
  241.     
  242.     MemoryContext savecxt;
  243.     
  244.     /* ----------------
  245.      *  get the current portal and group
  246.      * ----------------
  247.      */
  248.     entry = be_currentportal();
  249.     portal = entry->portal;
  250.     group = portal->groups;
  251.     
  252.     /* ----------------
  253.      *    switch to the portal's memory context so that
  254.      *  the tuples we allocate are returned to the user.
  255.      * ----------------
  256.      */
  257.     savecxt = MemoryContextSwitchTo((MemoryContext)entry->portalcxt);
  258.     
  259.     /* ----------------
  260.      *    If no tuple block yet, allocate one.
  261.      *  If the current block is full, allocate another one.
  262.      * ----------------
  263.      */
  264.     if (group->tuples == NULL) {
  265.     tuples = group->tuples = pbuf_addTuples();
  266.     tuples->tuple_index = 0;
  267.     } else {
  268.     tuples = group->tuples;
  269.     if (tuples->tuple_index == TupleBlockSize) {
  270.         tuples->next = pbuf_addTuples();
  271.         tuples = tuples->next;
  272.         tuples->tuple_index = 0;
  273.     }
  274.     }
  275.  
  276.     /* ----------------
  277.      *    Allocate space for a tuple.
  278.      * ----------------
  279.      */
  280.     tuples->values[tuples->tuple_index] = pbuf_addTuple(tuple->t_natts);
  281.     
  282.     /* ----------------
  283.      *    copy printable representations of the tuple's attributes
  284.      *  to the portal.
  285.      *
  286.      *  This seems silly, because the user's function which is calling
  287.      *  PQexec() or PQfn() will probably just convert this back into the
  288.      *  internal form anyways, but the point here is to provide a uniform
  289.      *  libpq interface and this is how the fe libpq interface currently
  290.      *  works.  Pretty soon we'll have to add code to let the fe or be
  291.      *  select the desired data representation and then deal with that.
  292.      *  This should not be too hard, as there already exist typrecieve()
  293.      *  and typsend() procedures for user-defined types (see pg_type.h)
  294.      *  -cim 2/11/91
  295.      * ----------------
  296.      */
  297.     values = tuples->values[tuples->tuple_index];
  298.     for (i = 0; i < tuple->t_natts; i++) {
  299.     attr = heap_getattr(tuple, InvalidBuffer, i+1, typeinfo, &isnull);
  300.     typoutput = typtoout((ObjectId) typeinfo[i]->atttypid);
  301.  
  302.     if (!isnull && ObjectIdIsValid(typoutput)) {
  303.         values[i] = fmgr(typoutput, attr);
  304.     } else 
  305.         values[i] = NULL;
  306.     }
  307.     
  308.     /* ----------------
  309.      *    increment tuple group counters
  310.      * ----------------
  311.      */
  312.     portal->no_tuples++;
  313.     group->no_tuples++;
  314.     tuples->tuple_index++;
  315.  
  316.     /* ----------------
  317.      *    return to the original memory context
  318.      * ----------------
  319.      */
  320.     MemoryContextSwitchTo(savecxt);
  321. }
  322.